home *** CD-ROM | disk | FTP | other *** search
- /* If the filename's path does not start with a back slash and it does, */
- /* not specify a drive, fopene_program looks first at the filename itself, */
- /* then appends it to any paths specified in a PATH-like environment */
- /* variable which has the same name as the filename's extension, then */
- /* appends it to any paths in the PATH enviroment variable. Under DOS 3 */
- /* or later, it finally appends it to the calling program's drive and */
- /* path. */
- /* fopene_program puts the actual drive, path and file name opened in */
- /* full_filename_opened, which is available to the calling program. If */
- /* it runs into a system problem which prevents it from determining the */
- /* drive and path, it uses the dummy "?:\?\", then the file name. */
- /* */
- /* I compiled fopen1 for use with Lattice C, Version 3. Some of its */
- /* features which may not be portable are: */
- /* fopene is a Lattice 3 variant version of fopen which automatically */
- /* searches the environment as described above. */
- /* Lattice function getdsk returns 0 if the default drive is A:, */
- /* 1 if it is B:, etc. */
- /* Lattice function getcd takes a drive number as its first argument, */
- /* with 0 for the default drive, 1 for A:, etc. It returns the current */
- /* directory in the variable pointed at by its second argument. The */
- /* current directory does not include either the drive letter or the */
- /* trailing back-slash. In particular, it returns an empty string for */
- /* the root directory. */
- /* dfind is a Lattice implementation of the DOS function which returns */
- /* the directory entry which matches the input file name. Sets the DOS */
- /* information in a structure which has a type FILEINFO, and it returns */
- /* 0 if it can make a match, -1 otherwise. */
- /* getenv(name) is a Lattice C function which returns a pointer to the */
- /* information following the = sign in the DOS environment string of the */
- /* form NAME=information. */
- /* strupr converts a string to upper case. */
- /* _DOS is a Lattice C system variable which contains the DOS major */
- /* version. */
- /* stcgfn is a Lattice expressions which get a file name path to a */
- /* string variable. The path does not have a trailing "\" */
- /* */
- /* Full identifiers in this program conform to the proposed ANSI */
- /* standard of at most 31 significant characters, and they are different */
- /* within the first 8 characters. Lattice C includes a -n compiler */
- /* switch which changes the number of significant characters in */
- /* identifiers from 8 to 39. While this program works without it, I */
- /* designed them to use it. */
- /* */
- /* Lew Paper */
- /* 4/18/87 */
- /***************************************************************************/
-
- #include <stdio.h>
- #include <string.h>
- #include <dos.h>
- #include <stdlib.h>
-
- #define COPY_TO_WORK(STRING) (void) strcpy(working_path_and_name, STRING)
- #define ADD_TO_WORK(STRING) (void) strcat(working_path_and_name, STRING)
- #define ADD_TO_FULL(STRING) (void) strcat(full_filename_opened, STRING)
-
- extern char _DOS; /* Lattice system variable. DOS major */
- /* version number */
-
- char full_filename_opened[67] = ""; /* d:[path]\name. Can be accessed */
- /* as an extern string in a calling */
- /* program. */
-
- static char upper_name[64]; /* Upper case of name */
-
- static char working_path_and_name[67]; /* Path and name without defaults */
-
-
- /* Takes a string which represents a full directory, path, filename and */
- /* extension for a file and removes all "." and ".." path components and */
- /* effects. */
-
- static int strip_dots()
-
- {
- char *pstart; /* Start of this subdirectory in */
- /* path */
- char *plast; /* Previous subdirectory in path */
- char *p;
-
- plast = &full_filename_opened[3]; /* Address of first character after */
- /* opening backslash */
- if (!(pstart = strchr(plast, '\\')))
- /* True if in a subdirectory of */
- /* path. False if in file name */
- return 0;
-
- ++pstart; /* Address of first character after */
- /* backslash */
- while (p = strchr(pstart, '\\')) /* True if in a subdirectory of */
- /* path. False if in file name */
- {
- if (*pstart == '.') /* Possible strip */
- {
- switch (p - pstart)
- {
- case 1: /* Must be . */
- (void) strcpy(pstart, p + 1);
- /* Get rid of this component */
- return 1;
- /*lint -unreachable */
- break; /* Defensive programming */
- case 2:
- if (*(pstart + 1) == '.')
- /* .. */
- {
- (void) strcpy(plast, p + 1);
- /* Get rid of this component and */
- /* the last one too */
- return 1;
- }
- break;
- default:
- break;
- }
- }
-
- plast = pstart;
- pstart = p + 1; /* Address of first character after */
- /* backslash */
- }
-
- return 0;
-
- }
-
-
- FILE *fopene_program(name, mode, argv0)
- char *name; /* File name to be opened */
- char *mode; /* Mode to open in. Probably only */
- /* makes sense as "r?" or "a?". */
- char *argv0; /* The value in argv[0] from */
- /* For DOS 3 or later, the calling */
- /* program. For earlier versions, */
- /* a null string. */
-
- {
- int relative; /* 1 if OK to test paths */
- char *env_path; /* Pointer to environment PATH */
- /* string */
- struct FILEINFO info; /* For dfind() */
- int not_found; /* Result of dfind() */
- char default_path[64];
- FILE *fp;
- char *p;
- unsigned n;
-
- /* Convert name to upper case */
- (void) strcpy(upper_name, name);
- (void) strupr(upper_name);
-
- if (fp = fopene(upper_name, mode, working_path_and_name))
- {
- #ifdef DEBUG
- fprintf(stderr, "fopene opened file %s and \n", name);
- fprintf(stderr, "set working_path_and_name to \"%s\"\n",
- working_path_and_name);
- #endif /* #ifdef DEBUG */
-
- if (working_path_and_name[0]) /* fopene puts path in */
- /* working_path_and_name if it */
- /* finds the file in the path */
- /* defined by the filename */
- /* extension. If it finds the file */
- /* in the default directory, it */
- /* sets working_path_and_name to */
- /* "". If it finds the file in the */
- /* environment PATH, it does one or */
- /* the other according to a rule */
- /* which I have yet to figure out. */
- {
- (void) strupr(working_path_and_name);
- if (*(working_path_and_name + strlen(working_path_and_name) - 1)
- != '\\')
- ADD_TO_WORK("\\");
- ADD_TO_WORK(upper_name);
- }
- else
- {
- relative = ((upper_name[0] != '\\') && (upper_name[1] != ':'));
- if (!relative) /* Must have opened without a path */
- COPY_TO_WORK(upper_name);
- else
- {
- #ifdef DEBUG
- fprintf(stderr, "Check directory for %s \n", upper_name);
- #endif /* #ifdef DEBUG */
- if (!dfind(&info, upper_name, 0))
- /* File opened by default path */
- COPY_TO_WORK(upper_name);
-
- /* Check which part of PATH opened the file */
- else
- {
- if (env_path = getenv("PATH"))
- do
- {
- if (p = strchr(env_path, ';'))
- n = p - env_path;
- else
- n = (unsigned) strlen(env_path);
- (void) strncpy(working_path_and_name, env_path, n);
- working_path_and_name[n] = (char) 0;
- if (*(working_path_and_name + n - 1) != '\\')
- ADD_TO_WORK("\\");
- ADD_TO_WORK(upper_name);
- env_path = p + 1; /* Junk, but not used, if p = NULL */
- #ifdef DEBUG
- fprintf(stderr, "Check directory for %s ",
- working_path_and_name);
- fputs("from PATH\n", stderr);
- #endif /* #ifdef DEBUG */
- not_found = dfind(&info, working_path_and_name, 0);
- } while (not_found && p);
-
- if (not_found)
- {
- fputs("Program error in function fopene_program.\n", stderr);
- fprintf(stderr, "Could not find file %s ", name);
- fputs("in the environment PATH\n", stderr);
- fprintf(stderr, "\"%s\"\n\n", getenv("PATH"));
- COPY_TO_WORK("?:\\?\\");
- }
- }
- }
- }
- }
- else /* Couldn't open the file with */
- /* environment paths */
- {
- #ifdef DEBUG
- fprintf(stderr, "fopene couldn't open file %s\n", name);
- #endif /* #ifdef DEBUG */
-
- if (_DOS >= 3 && relative)
- {
- /* Try to open with path of calling program */
- (void) stcgfp(working_path_and_name, argv0);
- (void) strupr(working_path_and_name);
- ADD_TO_WORK("\\");
- ADD_TO_WORK(upper_name);
- #ifdef DEBUG
- fprintf(stderr, "Try to open %s from argv0\n",
- working_path_and_name);
- #endif /* #ifdef DEBUG */
- fp = fopen(working_path_and_name, mode);
- }
- }
-
- /* Set full_filename_opened */
- if (fp)
- {
- p = working_path_and_name;
- if (working_path_and_name[1] == ':')
- /* Drive specified */
- {
- (void) strncpy(full_filename_opened, working_path_and_name, 2);
- p += 2;
- }
- else /* Use default drive */
- {
- full_filename_opened[0] = getdsk() + 'A';
- full_filename_opened[1] = ':';
- }
- full_filename_opened[2] = (char) 0;
-
- if (*p != '\\') /* Append to default path */
- {
- ADD_TO_FULL("\\");
- (void) getcd(full_filename_opened[0] - 'A' + 1, default_path);
- if (default_path[0])
- {
- ADD_TO_FULL(default_path);
- ADD_TO_FULL("\\");
- ADD_TO_FULL(p);
- }
- }
- else /* Don't use default path */
- ADD_TO_FULL(p);
- }
- else
- full_filename_opened[0] = (char) 0;
-
- /* Strip full_filename_opened of "." and ".." components */
- while (strip_dots()) /* Strip one component each cycle */
- /* strip_dots returns 1 if it */
- /* strips a component, 0 otherwise */
- ;
-
- return fp;
- }
-
- #ifdef DEBUG
-
- /* Test program for fopene_program */
-
- void main(argc, argv)
- int argc;
- char *argv[];
-
- {
- FILE *fp;
-
- if (argc < 2)
- {
- fputs("Usage: fopen1 <filename>\n", stderr);
- fputs(" where filename is [d][path]name.ext to be opened", stderr);
- fputs(" with no wild cards \n\n", stderr);
- exit(1);
- }
-
- if (fp = fopene_program(argv[1], "r", argv[0]))
- {
- fprintf(stderr, "Opened file %s\n", argv[1]);
- if (fclose(fp))
- fputs("Program error closing it\n", stderr);
- }
- else
- fprintf(stderr, "Unable to open file %s\n", argv[1]);
- fprintf(stderr, "full_filename_opened = \"%s\"\n\n",
- full_filename_opened);
- exit(0);
- }
- #endif /* ifdef DEBUG */